#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Web服务器模块
提供HTTP接口展示监控数据
"""

import json
import logging
import threading
import time
from datetime import datetime
from flask import Flask, jsonify, render_template_string, request
from flask_cors import CORS
from typing import Dict, Optional

logger = logging.getLogger(__name__)

class MonitorWebServer:
    """监控Web服务器"""
    
    def __init__(self, monitor_instance, host='0.0.0.0', port=8080):
        """
        初始化Web服务器
        
        Args:
            monitor_instance: 监控器实例
            host: 服务器主机地址
            port: 服务器端口
        """
        self.monitor = monitor_instance
        self.host = host
        self.port = port
        self.app = Flask(__name__)
        CORS(self.app)
        
        # 配置Flask
        self.app.config['JSON_AS_ASCII'] = False
        self.app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
        
        self._setup_routes()
        self._server_thread = None
        self._running = False
        
    def _setup_routes(self):
        """设置路由"""
        
        @self.app.route('/')
        def index():
            """主页面"""
            return render_template_string(self._get_dashboard_template())
        
        @self.app.route('/api/status')
        def get_status():
            """获取系统状态API"""
            try:
                status = self.monitor.get_system_status()
                return jsonify({
                    'success': True,
                    'data': status,
                    'timestamp': datetime.now().isoformat()
                })
            except Exception as e:
                logger.error(f"获取系统状态失败: {e}")
                return jsonify({
                    'success': False,
                    'error': str(e),
                    'timestamp': datetime.now().isoformat()
                }), 500
        
        @self.app.route('/api/alerts')
        def get_alerts():
            """获取告警信息API"""
            try:
                status = self.monitor.get_system_status()
                alerts = self.monitor.check_thresholds(status)
                return jsonify({
                    'success': True,
                    'data': alerts,
                    'count': len(alerts),
                    'timestamp': datetime.now().isoformat()
                })
            except Exception as e:
                logger.error(f"获取告警信息失败: {e}")
                return jsonify({
                    'success': False,
                    'error': str(e),
                    'timestamp': datetime.now().isoformat()
                }), 500
        
        @self.app.route('/api/health')
        def health_check():
            """健康检查API"""
            return jsonify({
                'status': 'healthy',
                'service': 'universal-server-monitor',
                'timestamp': datetime.now().isoformat(),
                'monitor_type': type(self.monitor.active_monitor).__name__ if hasattr(self.monitor, 'active_monitor') else 'Unknown'
            })
        
        @self.app.route('/api/thresholds')
        def get_thresholds():
            """获取阈值配置API"""
            try:
                thresholds = self.monitor.thresholds.to_dict()
                return jsonify({
                    'success': True,
                    'data': thresholds,
                    'timestamp': datetime.now().isoformat()
                })
            except Exception as e:
                logger.error(f"获取阈值配置失败: {e}")
                return jsonify({
                    'success': False,
                    'error': str(e),
                    'timestamp': datetime.now().isoformat()
                }), 500
    
    def _get_dashboard_template(self):
        """获取仪表板HTML模板"""
        return '''
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>通用服务器监控系统</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            color: #333;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        
        .header {
            text-align: center;
            color: white;
            margin-bottom: 30px;
        }
        
        .header h1 {
            font-size: 2.5em;
            margin-bottom: 10px;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
        }
        
        .header p {
            font-size: 1.2em;
            opacity: 0.9;
        }
        
        .dashboard {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }
        
        .card {
            background: white;
            border-radius: 15px;
            padding: 25px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.1);
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }
        
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 15px 40px rgba(0,0,0,0.15);
        }
        
        .card-title {
            font-size: 1.3em;
            font-weight: bold;
            margin-bottom: 15px;
            color: #4a5568;
            display: flex;
            align-items: center;
        }
        
        .card-title .icon {
            margin-right: 10px;
            font-size: 1.5em;
        }
        
        .metric {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 10px;
            padding: 8px 0;
            border-bottom: 1px solid #e2e8f0;
        }
        
        .metric:last-child {
            border-bottom: none;
            margin-bottom: 0;
        }
        
        .metric-label {
            font-weight: 500;
            color: #718096;
        }
        
        .metric-value {
            font-weight: bold;
            color: #2d3748;
        }
        
        .progress-bar {
            width: 100%;
            height: 8px;
            background-color: #e2e8f0;
            border-radius: 4px;
            overflow: hidden;
            margin-top: 5px;
        }
        
        .progress-fill {
            height: 100%;
            border-radius: 4px;
            transition: width 0.3s ease;
        }
        
        .progress-normal { background-color: #48bb78; }
        .progress-warning { background-color: #ed8936; }
        .progress-critical { background-color: #f56565; }
        
        .alerts {
            background: white;
            border-radius: 15px;
            padding: 25px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.1);
        }
        
        .alert {
            padding: 12px 16px;
            border-radius: 8px;
            margin-bottom: 10px;
            display: flex;
            align-items: center;
        }
        
        .alert:last-child {
            margin-bottom: 0;
        }
        
        .alert-warning {
            background-color: #fef5e7;
            border-left: 4px solid #ed8936;
            color: #744210;
        }
        
        .alert-critical {
            background-color: #fed7d7;
            border-left: 4px solid #f56565;
            color: #742a2a;
        }
        
        .alert-icon {
            margin-right: 10px;
            font-size: 1.2em;
        }
        
        .loading {
            text-align: center;
            color: #718096;
            font-style: italic;
        }
        
        .footer {
            text-align: center;
            color: white;
            margin-top: 30px;
            opacity: 0.8;
        }
        
        .refresh-btn {
            background: linear-gradient(135deg, #4299e1, #3182ce);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 25px;
            cursor: pointer;
            font-size: 1em;
            font-weight: 500;
            transition: all 0.3s ease;
            margin: 20px auto;
            display: block;
        }
        
        .refresh-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(66, 153, 225, 0.4);
        }
        
        .status-indicator {
            display: inline-block;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            margin-right: 8px;
        }
        
        .status-normal { background-color: #48bb78; }
        .status-warning { background-color: #ed8936; }
        .status-critical { background-color: #f56565; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🖥️ 通用服务器监控系统</h1>
            <p>实时监控系统资源使用情况</p>
        </div>
        
        <div id="dashboard" class="dashboard">
            <div class="loading">正在加载监控数据...</div>
        </div>
        
        <button class="refresh-btn" onclick="loadData()">🔄 刷新数据</button>
        
        <div id="alerts" class="alerts" style="display: none;">
            <div class="card-title">
                <span class="icon">⚠️</span>
                系统告警
            </div>
            <div id="alerts-content"></div>
        </div>
        
        <div class="footer">
            <p>© 2025 通用服务器监控系统 | 最后更新: <span id="last-update">--</span></p>
        </div>
    </div>

    <script>
        function formatBytes(bytes) {
            if (bytes === 0) return '0 B';
            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }
        
        function getProgressClass(percent, warningThreshold = 70, criticalThreshold = 85) {
            if (percent >= criticalThreshold) return 'progress-critical';
            if (percent >= warningThreshold) return 'progress-warning';
            return 'progress-normal';
        }
        
        function getStatusClass(percent, warningThreshold = 70, criticalThreshold = 85) {
            if (percent >= criticalThreshold) return 'status-critical';
            if (percent >= warningThreshold) return 'status-warning';
            return 'status-normal';
        }
        
        function createMetric(label, value, showProgress = false, percent = 0) {
            const progressHtml = showProgress ? 
                `<div class="progress-bar">
                    <div class="progress-fill ${getProgressClass(percent)}" style="width: ${percent}%"></div>
                </div>` : '';
            
            return `
                <div class="metric">
                    <span class="metric-label">${label}</span>
                    <span class="metric-value">${value}</span>
                </div>
                ${progressHtml}
            `;
        }
        
        function loadData() {
            Promise.all([
                fetch('/api/status').then(r => r.json()),
                fetch('/api/alerts').then(r => r.json())
            ]).then(([statusResponse, alertsResponse]) => {
                if (statusResponse.success) {
                    renderDashboard(statusResponse.data);
                }
                if (alertsResponse.success) {
                    renderAlerts(alertsResponse.data);
                }
                document.getElementById('last-update').textContent = new Date().toLocaleString('zh-CN');
            }).catch(error => {
                console.error('加载数据失败:', error);
                document.getElementById('dashboard').innerHTML = 
                    '<div class="card"><div class="card-title">❌ 数据加载失败</div><p>请检查服务器连接</p></div>';
            });
        }
        
        function renderDashboard(data) {
            const cpu = data.cpu || {};
            const memory = data.memory || {};
            const disk = data.disk || {};
            const network = data.network || {};
            
            let html = '';
            
            // CPU卡片
            html += `
                <div class="card">
                    <div class="card-title">
                        <span class="icon">🔥</span>
                        <span class="status-indicator ${getStatusClass(cpu.percent || 0)}"></span>
                        CPU 使用情况
                    </div>
                    ${createMetric('使用率', (cpu.percent || 0).toFixed(1) + '%', true, cpu.percent || 0)}
                    ${createMetric('核心数', cpu.count || 'N/A')}
                    ${createMetric('频率', cpu.frequency ? (cpu.frequency / 1000).toFixed(2) + ' GHz' : 'N/A')}
                </div>
            `;
            
            // 内存卡片
            html += `
                <div class="card">
                    <div class="card-title">
                        <span class="icon">💾</span>
                        <span class="status-indicator ${getStatusClass(memory.percent || 0)}"></span>
                        内存使用情况
                    </div>
                    ${createMetric('使用率', (memory.percent || 0).toFixed(1) + '%', true, memory.percent || 0)}
                    ${createMetric('总内存', formatBytes(memory.total || 0))}
                    ${createMetric('已使用', formatBytes(memory.used || 0))}
                    ${createMetric('可用', formatBytes(memory.available || 0))}
                </div>
            `;
            
            // 磁盘卡片
            if (Object.keys(disk).length > 0) {
                html += `
                    <div class="card">
                        <div class="card-title">
                            <span class="icon">💿</span>
                            磁盘使用情况
                        </div>
                `;
                
                for (const [mountpoint, diskInfo] of Object.entries(disk)) {
                    html += `
                        <div style="margin-bottom: 15px; padding-bottom: 15px; border-bottom: 1px solid #e2e8f0;">
                            <div style="font-weight: bold; margin-bottom: 8px;">
                                <span class="status-indicator ${getStatusClass(diskInfo.percent || 0)}"></span>
                                ${mountpoint}
                            </div>
                            ${createMetric('使用率', (diskInfo.percent || 0).toFixed(1) + '%', true, diskInfo.percent || 0)}
                            ${createMetric('总容量', formatBytes(diskInfo.total || 0))}
                            ${createMetric('可用', formatBytes(diskInfo.free || 0))}
                        </div>
                    `;
                }
                
                html += '</div>';
            }
            
            // 网络卡片
            html += `
                <div class="card">
                    <div class="card-title">
                        <span class="icon">🌐</span>
                        网络使用情况
                    </div>
                    ${createMetric('发送', formatBytes(network.bytes_sent || 0))}
                    ${createMetric('接收', formatBytes(network.bytes_recv || 0))}
                    ${createMetric('发送包数', (network.packets_sent || 0).toLocaleString())}
                    ${createMetric('接收包数', (network.packets_recv || 0).toLocaleString())}
                </div>
            `;
            
            document.getElementById('dashboard').innerHTML = html;
        }
        
        function renderAlerts(alerts) {
            const alertsContainer = document.getElementById('alerts');
            const alertsContent = document.getElementById('alerts-content');
            
            if (alerts.length === 0) {
                alertsContainer.style.display = 'none';
                return;
            }
            
            let html = '';
            alerts.forEach(alert => {
                const alertClass = alert.level === 'critical' ? 'alert-critical' : 'alert-warning';
                const icon = alert.level === 'critical' ? '🔴' : '🟡';
                
                html += `
                    <div class="alert ${alertClass}">
                        <span class="alert-icon">${icon}</span>
                        <span>${alert.message}</span>
                    </div>
                `;
            });
            
            alertsContent.innerHTML = html;
            alertsContainer.style.display = 'block';
        }
        
        // 页面加载时获取数据
        document.addEventListener('DOMContentLoaded', loadData);
        
        // 每30秒自动刷新
        setInterval(loadData, 30000);
    </script>
</body>
</html>
        '''
    
    def start(self):
        """启动Web服务器"""
        if self._running:
            logger.warning("Web服务器已在运行")
            return
        
        def run_server():
            try:
                logger.info(f"启动Web服务器: http://{self.host}:{self.port}")
                self.app.run(host=self.host, port=self.port, debug=False, threaded=True)
            except Exception as e:
                logger.error(f"Web服务器启动失败: {e}")
        
        self._server_thread = threading.Thread(target=run_server, daemon=True)
        self._server_thread.start()
        self._running = True
        
        # 等待服务器启动
        time.sleep(2)
        logger.info(f"Web服务器已启动，访问地址: http://{self.host}:{self.port}")
    
    def stop(self):
        """停止Web服务器"""
        if not self._running:
            return
        
        self._running = False
        logger.info("Web服务器已停止")
    
    def is_running(self):
        """检查Web服务器是否运行中"""
        return self._running and self._server_thread and self._server_thread.is_alive()